from turtle import Turtle
import turtle

# 设置游戏的窗口大小和背景颜色
turtle.screensize(800, 600, "pink")


class Maze(Turtle):
    size = 20  # 迷宫内一格墙的长宽

    def __init__(self, maze_list):
        # 需要先调用父类的初始化方法才能在初始化方法中调用父类的方法
        Turtle.__init__(self)
        self.maze_list = maze_list
        # 为了加快绘图速度隐藏海龟，速度设为最快
        self.hideturtle()
        self.speed(0)
        self.draw_walls()

    # 绘制迷宫内一格墙的过程
    def draw_wall(self):
        self.pendown()
        self.begin_fill()
        # 绘制墙的颜色
        self.fillcolor('red')
        # 首先画一个距离为20的横线，再向右旋转90度，循环4次形成方形
        for i in range(4):
            self.forward(self.size)
            self.right(90)
        self.end_fill()
        self.penup()

    # 绘制整个迷宫的墙
    def draw_walls(self):
        self.penup()
        # 从 (-130, 130) 开始
        self.goto(-130, 130)
        # 打印墙，横纵循环13次（整个迷宫的长和宽由13格墙组成）
        for row in range(13):
            for col in range(13):
                # 主函数中的maze_list里面的1则打印出一格墙
                if self.maze_list[row][col] == 1:
                    self.draw_wall()
                # 右移一列
                self.goto(self.size * (col + 1) - 130, 130 - self.size * row)
            # 下移一行
            self.goto(-130, 130 - self.size * (row + 1))


class Player(Turtle):
    def area(self, maze_list, start_m, start_n, end_m, end_n):
        # 父类初始化
        Turtle.__init__(self)
        # 初始的横纵坐标
        self.m = start_m
        self.n = start_n
        # 终点的横纵坐标
        self.end_m = end_m
        self.end_n = end_n
        # 迷宫地图
        self.maze_list = maze_list
        self.hideturtle()
        self.speed(0)
        self.penup()
        # 玩家移到对应的位置
        self.goto(self.n * 20 - 120, 120 - self.m * 20)
        # 生成玩家
    def play(self):
        self.shape('turtle')
        self.color('yellow')
        # 玩家初始方向
        self.setheading(270)
        self.showturtle()


    # 当玩家到达终点时，显示'you win!'
    def reach_exit(self, m, n):
        if m == self.end_m and n == self.end_n:
            # 走出迷宫，显示'you win!'
            text = turtle.Turtle()
            text.hideturtle()
            text.penup()
            text.goto(-125, -10)
            text.color('blue')
            text.write('you win!', font=('SimHei', 48, 'bold'))

    # 定义玩家可移动的位置，即只允许在迷宫内的通道里移动
    def canmove(self, m, n):
        # 遇到0允许移动
        return self.maze_list[m][n] == 0

    # 玩家移动时位置发生的变化
    def move(self, m, n):
        self.m = m
        self.n = n
        self.goto(self.n * 20 - 120, 120 - self.m * 20)
        self.reach_exit(m, n)

    # 向上移动
    def go_up(self):
        if self.canmove(self.m - 1, self.n):
            self.setheading(90)
            self.move(self.m - 1, self.n)

    # 向下移动
    def go_down(self):
        if self.canmove(self.m + 1, self.n):
            self.setheading(270)
            self.move(self.m + 1, self.n)

    # 向左移动
    def go_left(self):
        if self.canmove(self.m, self.n - 1):
            self.setheading(180)
            self.move(self.m, self.n - 1)

    # 向右移动
    def go_right(self):
        if self.canmove(self.m, self.n + 1):
            self.setheading(0)
            self.move(self.m, self.n + 1)

class Controller(Turtle):
  def __init__(self, go_up, go_down, go_left, go_right):
    # 父类初始化
    Turtle.__init__(self)
    # 初始值设置
    self.go_up = go_up
    self.go_down = go_down
    self.go_left = go_left
    self.go_right = go_right
    # 绘制控制器
    self.hideturtle()
    self.speed(0)
    self.draw_btn('上', -15, 165)
    self.draw_btn('下', -15, -135)
    self.draw_btn('左', -165, 15)
    self.draw_btn('右', 135, 15)
    # 绑定点击事件
    screen = self.getscreen()
    screen.onclick(self.handlescreenclick)

  #此处与绘制迷宫内一格墙的方法雷同，不做解释
  def draw_btn(self, name, x, y):
    self.penup()
    self.goto(x, y)
    self.begin_fill()
    self.fillcolor('#ffffff')
    for i in range(4):
      self.forward(30)
      self.right(90)
    self.end_fill()
    self.color('#000000')
    self.goto(x + 7, y - 20)
    self.write(name, font = ('SimHei', 12, 'bold'))

  #当点击事件发生时利用abs函数进行比较判断
  def handlescreenclick(self, x, y):
    if y > 0 and abs(x) < y:
      self.go_up()
    if y < 0 and abs(x) < -y:
      self.go_down()
    if x < 0 and abs(y) < -x:
      self.go_left()
    if x > 0 and abs(y) < x:
      self.go_right()

maze_list = [
  [1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1],
  [1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
  [1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1],
  [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1],
  [1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1],
  [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1],
  [1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1],
  [1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1],
  [1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1],
  [1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1],
  [1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1],
  [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1],
  [1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1]
]

player = Player()
player.area(maze_list, 0, 5, 12, 7)
player.play()
while True:
    Maze(maze_list)
#0,5表示玩家起始的位置；12,7表示终点的位置
    Controller(player.go_up, player.go_down, player.go_left, player.go_right)
